package Teste2;

import java.util.LinkedList;
import java.util.Set;



import puzzle.Puzzle;
import respuzzle.EstadoPuzzle;
import respuzzle.ObjectivoPuzzle;
import respuzzle.OperadorMover;
import mecproc.*;


public class bateriaPuzzle {
	
	//enum tipoProc {Profundidade, ProfundidadeLimtada, ProfundidadeIterativa, Largura, CustoUniforme, Sofrega, AA}
	enum tipoProc { CustoUniforme, Sofrega, AA}
	
	public static void main(String[] args){
		
		//----------------------
		//----Tabuleiros 3x3----
		//----------------------
		
		Puzzle puzzelFinal = new Puzzle(new int[][] {{1,2,3},{4,5,6},{7,8,0}});
		
		LinkedList<Puzzle> puzzles = new LinkedList<Puzzle>();
		//puzzles.add(new Puzzle(new int[][] {{1,2,3},{8,4,5},{6,7,0}}));
		puzzles.add(new Puzzle(new int[][] {{8,4,5},{6,1,2},{3,7,0}}));
		
		//----------------------
		//----Tabuleiros 4x4----
		//----------------------
		//int[][] tab14x4={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,0,15}};
		//int[][] tab1={{8,4,5,9},{10,6,1,2},{3,11,7,12},{13,14,0,15}};
		//int[][] tabFinal={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};
		
		//----------------------
		LinkedList<No<EstadoPuzzle>> solucao;
		for(Puzzle puzzle: puzzles){
			System.out.println(puzzle.toString());
			for(tipoProc tipo: tipoProc.values()){
				System.out.println(tipo+":");
				try{
					solucao = execute(puzzle, puzzelFinal, tipo);
				}catch(OutOfMemoryError e){
					System.out.println(e.getMessage());
				}
				System.out.println("--------------------------------");
			}
		}
		
		
		
		
	}
	
	private void mostrarSolucao(LinkedList<No<EstadoPuzzle>> solucao){
		//mostrar solucao
		if(solucao != null) {
			System.out.println("Movimentos:");
			for(No<EstadoPuzzle> no : solucao)
					System.out.println(no.getEstado().toString());
		}
		else
			System.out.println("Solucao nao encontrada");
	}
	
	private static LinkedList<No<EstadoPuzzle>> execute(Puzzle puzzleInicial, Puzzle puzzleFinal, tipoProc tipo) throws OutOfMemoryError{
		MecProcura<EstadoPuzzle> mecProcura;
		
		OperadorMover[] operadores = {
				new OperadorMover(Puzzle.Movimento.BAIXO),
				new OperadorMover(Puzzle.Movimento.CIMA),
				new OperadorMover(Puzzle.Movimento.DIR),
				new OperadorMover(Puzzle.Movimento.ESQ)};
		
		switch (tipo) {
//		case Profundidade:
//			mecProcura = new MecProcProf<EstadoPuzzle>();
//			break;
//		case ProfundidadeIterativa:
//			mecProcura = new MecProcProfIter<EstadoPuzzle>(0,1);
//			break;
//		case ProfundidadeLimtada:
//			mecProcura = new MecProcProfLimit<EstadoPuzzle>(30);
//			break;
		case CustoUniforme:
			mecProcura = new MecProcCustoUnif<EstadoPuzzle>();
			break;
		case AA:
			mecProcura = new MecProcAA<EstadoPuzzle>();
			break;
//		case Largura:
//			mecProcura = new MecProcLarg<EstadoPuzzle>();
//			break;
		default:
			mecProcura = new MecProcSofrega<EstadoPuzzle>();
			break;
		}
		
		return mecProcura.procurar(new EstadoPuzzle(puzzleInicial),new ObjectivoPuzzle(new EstadoPuzzle(puzzleFinal)), operadores);

	}
}


